"""
@File    :   password_strength.py
@Time    :   2024/03/19 10:56:27
@Author  :   Qrj
@Email   :   923207736@qq.com
@description   :   密码强度相关工具类
"""

from functools import lru_cache
from re import Pattern, compile

from src.business.admin.system.settings.enums import (
    PasswordStrengthEnum,
    PasswordStrengthRegexpEnum,
    PasswordStrengthRegexpValidateErrorMsgEnum,
)


class PasswordStrengthUtil:
    """密码强度工具类"""

    @staticmethod
    @lru_cache
    def get_regexp(
        psw_strength: PasswordStrengthEnum, min_length: int, max_length: int
    ) -> Pattern:
        """获取密码强度的正则表达式

        Args:
            psw_strength: 密码强度
            min_length (int): 密码最小长度
            max_length (int): 密码最大长度

        Returns:
            str: 正则表达式
        """
        regexp_strength = getattr(PasswordStrengthRegexpEnum, psw_strength.name).value
        # 密码个数为指定区间内字符
        regexp_length = "{" + str(min_length) + "," + str(max_length) + "}$"
        re_pattern = regexp_strength + regexp_length
        return compile(re_pattern)

    @staticmethod
    @lru_cache
    def get_regexp_validate_error_msg(
        psw_strength: PasswordStrengthEnum, min_length: int, max_length: int
    ) -> str:
        """获取密码强度验证失败时对应的错误信息

        Args:
            psw_strength (PasswordStrengthEnum): 密码强度
            min_length (int): 密码最小长度
            max_length (int): 密码最大长度

        Returns:
            str: 错误信息
        """
        error_msg = getattr(
            PasswordStrengthRegexpValidateErrorMsgEnum, psw_strength.name
        ).value
        error_msg = error_msg.format(min_length, max_length)
        return error_msg

    @staticmethod
    def verify_password_strength(
        psw_strength: PasswordStrengthEnum,
        min_length: int,
        max_length: int,
        password: str,
    ) -> tuple[bool, str | None]:
        """验证密码是否符合密码强度要求

        Args:
            psw_strength (PasswordStrengthEnum): 密码强度
            min_length (int): 密码最小长度
            max_length (int): 密码最大长度
            password (str): 密码

        Returns:
            tuple[bool, str | None]: 是否符合密码强度要求、错误信息
        """
        # 获取正则模式
        re_pattern = PasswordStrengthUtil.get_regexp(
            psw_strength, min_length, max_length
        )
        # 进行正则匹配
        re_result = re_pattern.search(password)
        if re_result is None:
            return (
                False,
                PasswordStrengthUtil.get_regexp_validate_error_msg(
                    psw_strength, min_length, max_length
                ),
            )
        return True, None
